package com.ls.fw.sdk.open;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ls.fw.commons.open.utils.OpenUtil;
import com.ls.fw.sdk.open.utils.PostUtil;

import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * 请求客户端
 */
public class OpenClient {
	public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");

	protected Logger logger = LoggerFactory.getLogger(getClass());
	
	private String appKey;
	private String appSecret;

	private String appKeyName = "appKey";
	private String signName = "sign";
	private String timestampName = "timestrap";

    OkHttpClient client = new OkHttpClient()
    		.newBuilder().readTimeout(5, TimeUnit.MINUTES)
    		.writeTimeout(5, TimeUnit.MINUTES)
    		.connectTimeout(5, TimeUnit.MINUTES)
    		.build();
    
	public OpenClient(String appKey, String appSecret) {
		this.appKey = appKey;
		this.appSecret = appSecret;
	}
	
	/**
	 * 发送请求
	 * @param url
	 * @param params
	 * @return 返回XML数据
	 */
	public String postXML(String url,Map<String, String> params) {
		return this.post(url, params, PostUtil.XML);
	}
	
	/**
	 * 发送请求
	 * @param url
	 * @param entity
	 * @return 返回XML数据
	 */
	public String postXML(String url, Object entity) {
		Map<String, String> paramsMap = OpenUtil.buildParamsMap(entity);
		return this.postXML(url, paramsMap);
	}
	
	
	/**
	 * 发送请求
	 * @param url
	 * @param params
	 * @return 返回JSON数据
	 */
	public String postJSON(String url,Map<String, String> params) {
		return this.post(url, params,PostUtil.JSON);
	}

	public String postJSON(String url,Map<String, String> params,String requestBody) {
		return this.postJSON(url, params,requestBody);
	}
	
	/**
	 * 发送请求
	 * @param url
	 * @param entity
	 * @return 返回JSON数据
	 */
	public String postJSON(String url, Object entity) {
		Map<String, String> paramsMap = OpenUtil.buildParamsMap(entity);
		return this.postJSON(url, paramsMap);
	}
	
	/**
	 * 发送请求
	 * @param url 请求连接
	 * @param params 请求参数
	 * @return 服务端返回的内容
	 */
	public String post(String url,Map<String, String> params,String requestBody) {
		Map<String, String> _params = getSignedParaMap(params);
		try {
			return post(buildUri(url, _params), requestBody);
		} catch (Exception e) {
			throw new ClientException(e.getMessage());
		}
	}

	
	/**
	 * 
	 * @author lisheng
	 * @date 2016年6月11日 下午1:21:32
	 * @version V1.0
	 * @param params
	 * @return
	 */
	private Map<String, String> getSignedParaMap(Map<String, String> params) {
		Map<String, String> _params =new HashMap<>();
		_params.putAll(params);
		_params.put(appKeyName, this.appKey);
		_params.put(timestampName, String.valueOf(System.currentTimeMillis()));
		
		String sign = null;
		try {
			sign = OpenUtil.buildSign(_params, this.appSecret,null);
		} catch (IOException e1) {
			e1.printStackTrace();
			throw new ClientException("签名构建失败");
		}
		
		_params.put(signName, sign);
		return _params;
	}
	

	public String post(String url, String json) throws IOException {
	  RequestBody body = RequestBody.create(JSON, json);
	  Request request = new Request.Builder()
	      .url(url)
	      .post(body)
	      .build();
	  logger.info(request.toString()+":"+json);
	  Response response = client.newCall(request).execute();
	  return response.body().string();
	}

	
	public String get(String url,Map<String, String> paraMap) {
		Map<String, String> _params = getSignedParaMap(paraMap);
		return get(buildUri(url, _params));
	}
	
	
	public String get(String url) {
		  logger.info("url"+":"+url);
	  try {
			Request request = new Request.Builder()
			      .url(url) 
			      .get()
			      .build();
			  Response response = client.newCall(request).execute();
			  return response.body().string();
		} catch (Exception e) {
			throw new ClientException(e.getMessage());
		}
	}
	public String buildUri(String uri, Map<String, String> paraMap) {
		StringBuilder sb = new StringBuilder();
		uri = StringUtils.trim(uri);
		uri = StringUtils.removeEnd(uri, "/");
		uri = StringUtils.removeEnd(uri, "?");
		uri = StringUtils.removeEnd(uri, "&");
		sb.append(uri);
		if (paraMap != null && !paraMap.isEmpty()) {
			sb.append("?");
			Iterator<Entry<String, String>> iterator = paraMap.entrySet()
					.iterator();
			while (iterator.hasNext()) {
				Map.Entry<String, String> pair = iterator.next();
				try {
					String keyString = pair.getKey();
					String valueString = pair.getValue();
					sb.append(keyString);
					sb.append("=");
					sb.append(valueString);
					sb.append("&");
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
				}
			}
		}
		return StringUtils.removeEnd(sb.toString(), "&");
	}


	public String getAppKey() {
		return appKey;
	}

	public void setAppKey(String appKey) {
		this.appKey = appKey;
	}

	public String getAppSecret() {
		return appSecret;
	}

	public void setAppSecret(String appSecret) {
		this.appSecret = appSecret;
	}

	public String getAppKeyName() {
		return appKeyName;
	}

	public void setAppKeyName(String appKeyName) {
		this.appKeyName = appKeyName;
	}

	public String getSignName() {
		return signName;
	}

	public void setSignName(String signName) {
		this.signName = signName;
	}

	public String getTimestampName() {
		return timestampName;
	}

	public void setTimestampName(String timestampName) {
		this.timestampName = timestampName;
	}

}
